package com.guaoran.utils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;

/**
 * weixin
 * @author guaoran
 */
public class HttpClient implements Serializable {
	private static final long serialVersionUID = -4420082458842011070L;
	private static final int ConnectionTimeout = 25000;
	private static final int ReadTimeout = 25000;

	public Response get(String url) throws Exception {
		URL urls = new URL(url);
		if (urls.getProtocol().toLowerCase().equals("https")) {
			return httpRequest(url, "GET", null);
		}else{
			return httpRequestNew(url, "GET", null);
		}
	}

	public Response postXml(String url, String xml) throws Exception {
		return httpRequest(url, "POST", xml);
	}

	private Response httpRequestNew(String url, String method, String postData) throws Exception {
		Response res = null;
		OutputStream output = null;
		HttpURLConnection http = null;
		try {
			http = getHttpURLConnection(url);

			if (http != null) {
				if ((method.equals("POST")) && (postData != null)) {
					byte[] bytes = postData.getBytes("UTF-8");

					http.setRequestProperty("Content-Length",
							Integer.toString(bytes.length));

					http.connect();

					output = http.getOutputStream();
					output.write(bytes);
					output.flush();
					output.close();
				} else {
					http.connect();
				}
			}

			res = new Response(http);

			if (res.getStatus() == 200) {
				return res;
			}
		} catch (IOException ex) {
			throw new Exception(ex.getMessage(), ex);
		}
		return res;
	}
	
	private Response httpRequest(String url, String method, String postData)
			throws Exception {
		Response res = null;
		OutputStream output = null;
		HttpsURLConnection https = null;
		try {
			https = getHttpsURLConnection(url);

			if (https != null) {
				setHttpsHeader(https, method);

				if ((method.equals("POST")) && (null != postData)) {
					byte[] bytes = postData.getBytes("UTF-8");

					https.setRequestProperty("Content-Length",
							Integer.toString(bytes.length));

					https.connect();

					output = https.getOutputStream();
					output.write(bytes);
					output.flush();
					output.close();
				} else {
					https.connect();
				}

				res = new Response(https);

				if (res.getStatus() == 200) {
					return res;
				}
			}
		} catch (NoSuchAlgorithmException ex) {
			throw new Exception(ex.getMessage(), ex);
		} catch (KeyManagementException ex) {
			throw new Exception(ex.getMessage(), ex);
		} catch (NoSuchProviderException ex) {
			throw new Exception(ex.getMessage(), ex);
		} catch (IOException ex) {
			throw new Exception(ex.getMessage(), ex);
		}
		return res;
	}

	private HttpsURLConnection getHttpsURLConnection(String url)
			throws IOException {
		URL urlGet = new URL(url);

		HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) urlGet
				.openConnection();
		return httpsUrlConnection;
	}

	private HttpURLConnection getHttpURLConnection(String url)
			throws IOException {
		URL urlGet = new URL(url);
		HttpURLConnection con = (HttpURLConnection) urlGet.openConnection();
		return con;
	}

	private void setHttpsHeader(HttpsURLConnection httpsUrlConnection,
			String method) throws NoSuchAlgorithmException,
			KeyManagementException, NoSuchProviderException, IOException {
		TrustManager[] tm = { new MyX509TrustManager() };

		SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");

		sslContext.init(null, tm, new SecureRandom());

		SSLSocketFactory ssf = sslContext.getSocketFactory();

		httpsUrlConnection.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");

		httpsUrlConnection
				.setRequestProperty(
						"User-Agent",
						"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");

		httpsUrlConnection.setDoOutput(true);

		httpsUrlConnection.setDoInput(true);

		httpsUrlConnection.setRequestMethod(method);

		if (ConnectionTimeout > 0) {
			httpsUrlConnection.setConnectTimeout(ConnectionTimeout);
		} else {
			httpsUrlConnection.setConnectTimeout(10000);
		}

		if (ReadTimeout > 0) {
			httpsUrlConnection.setReadTimeout(ReadTimeout);
		} else {
			httpsUrlConnection.setReadTimeout(10000);
		}

		httpsUrlConnection.setRequestProperty("Charsert", "UTF-8");

		httpsUrlConnection.setSSLSocketFactory(ssf);
	}

	private void setHttpHeader(HttpURLConnection httpUrlConnection,
			String method) throws IOException {
		httpUrlConnection.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");

		httpUrlConnection
				.setRequestProperty(
						"User-Agent",
						"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");

		httpUrlConnection.setDoOutput(true);

		httpUrlConnection.setDoInput(true);

		httpUrlConnection.setRequestMethod(method);

		if (ConnectionTimeout > 0) {
			httpUrlConnection.setConnectTimeout(ConnectionTimeout);
		} else {
			httpUrlConnection.setConnectTimeout(10000);
		}

		if (ReadTimeout > 0) {
			httpUrlConnection.setReadTimeout(ReadTimeout);
		} else {
			httpUrlConnection.setReadTimeout(10000);
		}

		httpUrlConnection.setRequestProperty("Charsert", "UTF-8");
	}

	public String upload(String url, File file) throws IOException,
			NoSuchAlgorithmException, NoSuchProviderException,
			KeyManagementException {
		HttpURLConnection http = null;
		StringBuffer bufferRes = new StringBuffer();
		try {
			String BOUNDARY = "----WebKitFormBoundaryiDGnV9zdZA1eM1yL";

			http = getHttpURLConnection(url);

			setHttpHeader(http, "POST");

			http.setUseCaches(false);

			http.setRequestProperty("connection", "Keep-Alive");

			http.setRequestProperty(
					"Content-Type",
					new StringBuilder()
							.append("multipart/form-data; boundary=")
							.append(BOUNDARY).toString());

			OutputStream out = null;

			DataInputStream dataIns = null;
			try {
				out = new DataOutputStream(http.getOutputStream());
				byte[] end_data = new StringBuilder().append("\r\n--")
						.append(BOUNDARY).append("--\r\n").toString()
						.getBytes();
				StringBuilder sb = new StringBuilder();
				sb.append("--");
				sb.append(BOUNDARY);
				sb.append("\r\n");
				sb.append(
						"Content-Disposition: form-data;name=\"media\";filename=\"")
						.append(file.getName()).append("\"\r\n");
				sb.append("Content-Type:application/octet-stream\r\n\r\n");
				byte[] data = sb.toString().getBytes();
				out.write(data);

				dataIns = new DataInputStream(new FileInputStream(file));

				byte[] bufferOut = new byte[1024];
				int bytes;
				while ((bytes = dataIns.read(bufferOut)) != -1) {
					out.write(bufferOut, 0, bytes);
				}
				out.write("\r\n".getBytes());
				dataIns.close();
				out.write(end_data);
				out.flush();
			} finally {
				if (out != null) {
					out.close();
				}

			}

			InputStream ins = null;
			try {
				ins = http.getInputStream();
				BufferedReader read = new BufferedReader(new InputStreamReader(
						ins, "UTF-8"));

				bufferRes = new StringBuffer();
				String valueString;
				while ((valueString = read.readLine()) != null) {
					bufferRes.append(valueString);
				}
			} finally {
				if (ins != null)
					ins.close();
			}
		} finally {
			if (http != null) {
				http.disconnect();
			}
		}
		return bufferRes.toString();
	}

	public String uploadHttps(String url, File file) throws IOException,
			NoSuchAlgorithmException, NoSuchProviderException,
			KeyManagementException {
		HttpsURLConnection https = null;
		StringBuffer bufferRes = new StringBuffer();
		try {
			String BOUNDARY = "----WebKitFormBoundaryiDGnV9zdZA1eM1yL";

			https = getHttpsURLConnection(url);

			setHttpsHeader(https, "POST");

			https.setUseCaches(false);

			https.setRequestProperty("connection", "Keep-Alive");

			https.setRequestProperty("Content-Type", new StringBuilder()
					.append("multipart/form-data; boundary=").append(BOUNDARY)
					.toString());

			OutputStream out = null;

			DataInputStream dataIns = null;
			try {
				out = new DataOutputStream(https.getOutputStream());
				byte[] end_data = new StringBuilder().append("\r\n--")
						.append(BOUNDARY).append("--\r\n").toString()
						.getBytes();
				StringBuilder sb = new StringBuilder();
				sb.append("--");
				sb.append(BOUNDARY);
				sb.append("\r\n");
				sb.append(
						"Content-Disposition: form-data;name=\"media\";filename=\"")
						.append(file.getName()).append("\"\r\n");
				sb.append("Content-Type:application/octet-stream\r\n\r\n");
				byte[] data = sb.toString().getBytes();
				out.write(data);

				dataIns = new DataInputStream(new FileInputStream(file));

				byte[] bufferOut = new byte[1024];
				int bytes;
				while ((bytes = dataIns.read(bufferOut)) != -1) {
					out.write(bufferOut, 0, bytes);
				}
				out.write("\r\n".getBytes());
				dataIns.close();
				out.write(end_data);
				out.flush();
			} finally {
				if (out != null) {
					out.close();
				}

			}

			InputStream ins = null;
			try {
				ins = https.getInputStream();
				BufferedReader read = new BufferedReader(new InputStreamReader(
						ins, "UTF-8"));

				bufferRes = new StringBuffer();
				String valueString;
				while ((valueString = read.readLine()) != null) {
					bufferRes.append(valueString);
				}
			} finally {
				if (ins != null)
					ins.close();
			}
		} finally {
			if (https != null) {
				https.disconnect();
			}
		}
		return bufferRes.toString();
	}
}